module dva2pa (
    input clk,
    input rst,
    input flush,
    input stall,

    input  [31:0] vaddr,
    input         vvalid,
    input         is_store,

    output [31:0] paddr,
    output        pvalid,

    input  [31:0] cp0_config0,
    output        uncache,

    /* TLB search (IF->port0; EXE->port1) */
    input         tlb_found   ,
    input  [19:0] tlb_pfn     ,
    input  [ 2:0] tlb_c       ,
    input         tlb_d       ,
    input         tlb_v       ,
    output [18:0] tlb_vpn2    ,
    output        tlb_odd_page,

    /* TLB exception */
    output        tlb_refill  ,
    output        tlb_invalid ,
    output        tlb_modified
);

  wire   unmapped = vaddr[31] & !vaddr[30]; // kseg0 & kseg1 unmapped (0x80000000 ~ 0xbfffffff)

  // tlb0 miss signal
  reg dtlb0_miss_r;

  always@(posedge clk) begin
    if (rst || (dtlb0_miss_r && !stall) || flush) begin
      dtlb0_miss_r <= 1'b0;
    end else if (vvalid && tlb_refill) begin
      dtlb0_miss_r <= 1'b1;
    end
  end

  assign pvalid = (tlb_found || dtlb0_miss_r || unmapped) && vvalid;

  assign tlb_vpn2     = vaddr[31:13];
  assign tlb_odd_page = vaddr[12];

  `ifdef RUN_SIM
  assign tlb_refill   = 1'b0;
  assign tlb_invalid  = 1'b0;
  assign tlb_modified = 1'b0;
  assign paddr = unmapped ? {3'd0, vaddr[28:0]}
                          : vaddr;
  `else
  assign tlb_refill   = !unmapped && !tlb_found;
  assign tlb_invalid  = !unmapped &&  tlb_found && !tlb_v;
  assign tlb_modified = !unmapped &&  tlb_found &&  tlb_v && !tlb_d && is_store;
  assign paddr = unmapped ? {3'd0, vaddr[28:0]}
                          : {tlb_pfn, vaddr[11:0]};
  `endif

  `ifdef RUN_SIM
  assign uncache = unmapped  &&  vaddr[29]                             || // kseg1 uncached
                  unmapped  && !vaddr[29] && cp0_config0[2:0] != 3'h3 ; // kseg0 uncached
  `else
  assign uncache = unmapped  &&  vaddr[29]                             || // kseg1 uncached
                  unmapped  && !vaddr[29] && cp0_config0[2:0] != 3'h3 || // kseg0 uncached
                  !unmapped && tlb_c != 3'h3                          ;  // umapped seg determined by tlb_c
  `endif
endmodule